home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / frontend / vc.c
C/C++ Source or Header  |  1999-01-01  |  15KB  |  458 lines

  1. /*  Frontend for vbcc                       */
  2. /*  (c) in 1995-98 by Volker Barthelmann    */
  3. /*  #define AMIGA for Amiga-Version         */
  4.  
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8.  
  9. #ifdef AMIGA
  10. #include <dos/dos.h>
  11. #include <dos/dosasl.h>
  12. #include <exec/libraries.h>
  13. #include <clib/dos_protos.h>
  14.  
  15. extern struct Library *DOSBase;
  16.  
  17. /*  Must be 32bit-aligned - I know it will be if compiled with vbcc.    */
  18. struct FileInfoBlock fib;
  19. #endif
  20.  
  21. struct NameList{
  22.     struct NameList *next;
  23.     char *obj;
  24. } *first_obj=0,*last_obj=0,*first_scratch=0,*last_scratch=0;
  25.  
  26. /*  Limit fuer Laenge der Namen (wegen Wildcards)   */
  27. #define NAMEBUF 1000    /*  MUST BE >= ~TMPNAM_L+7  */
  28. #define USERLIBS 1000
  29.  
  30. /*  Ab dieser Laenge werden Objektfiles nicht direkt uebergeben,    */
  31. /*  sondern aus einem File an den Linker uebergeben                 */
  32. #ifdef AMIGA
  33. int MAXCLEN=500;
  34. #else
  35. int MAXCLEN=32000;
  36. #endif
  37.  
  38. #define SCHEDULER 4096
  39. #define NOTMPFILE 2048
  40. #define OUTPUTSET 1024
  41. #define NOSTDLIB 512
  42. #define VERBOSE 256
  43. #define VERYVERBOSE 128
  44. #define KEEPSCRATCH 64
  45.  
  46. #define PPSRC 1
  47. #define CCSRC 2
  48. #define SCSRC 3
  49. #define ASSRC 4
  50. #define OBJ 5
  51.  
  52. char empty[]="";
  53. /*  Namen der einzelnen Phasen  */
  54. char *ppname=empty,*ccname=empty,*asname=empty,*ldname=empty,*l2name=empty;
  55. char *rmname=empty,*scname=empty;
  56. /*  dasselbe fuer VERBOSE   */
  57. char *ppv=empty,*ccv=empty,*asv=empty,*ldv=empty,*l2v=empty;
  58. char *rmv=empty,*scv=empty;
  59.  
  60. /*  Linker-Commandfile  */
  61. char *cf="@%s";
  62.  
  63. #if defined(AMIGA)
  64. const char *config_name="vc.config";
  65. const char *search_dirs[]={"","ENV:","VBCC:"};
  66. char *ul="vlib:%s.lib";
  67. #elif defined(WINTEL)
  68. const char *config_name="vc.cfg";
  69. const char *search_dirs[]={"","%VCCFG%\\"};
  70. char *ul="-l%s";
  71. #else
  72. const char *config_name="vc.config";
  73. const char *search_dirs[]={"","~/","/etc/"};
  74. char *ul="-l%s";
  75. #endif
  76.  
  77. /*  String fuer die Default libraries   */
  78. char userlibs[USERLIBS];
  79. char *nomem="Not enough memory!\n";
  80.  
  81. char *destname="a.out";
  82. char namebuf[NAMEBUF+1],namebuf2[NAMEBUF+1];
  83. char oldfile[NAMEBUF+2];
  84.  
  85. char *config;
  86. char **confp;
  87.  
  88. int typ(char *);
  89. char *add_suffix(char *,char *);
  90. void raus(int);
  91.  
  92. char *command,*options,*linkcmd,*objects,*libs,*ppopts;
  93. #ifdef AMIGA
  94. struct AnchorPath *ap;
  95. #endif
  96.  
  97. int linklen=10,flags=0;
  98.  
  99. void free_namelist(struct NameList *p)
  100. {
  101.     struct NameList *m;
  102.     while(p){
  103.         m=p->next;
  104.         if(flags&VERYVERBOSE){
  105.             puts("free p->obj");
  106.             if(!p->obj) puts("IS ZERO!!"); else puts(p->obj);
  107.         }
  108.         free((void *)p->obj);
  109.         if(flags&VERYVERBOSE){puts("free p"); if(!p) puts("IS ZERO!!");}
  110.         free((void *)p);
  111.         p=m;
  112.     }
  113. }
  114. void del_scratch(struct NameList *p)
  115. {
  116.     while(p){
  117.         sprintf(command,rmname,p->obj);
  118.         if(flags&VERBOSE) printf("%s\n",command);
  119.         if(system(command)){printf("%s failed\n",command);raus(20);}
  120.         p=p->next;
  121.     }
  122. }
  123. void raus(int rc)
  124. {
  125.     if(confp)   free(confp);
  126.     if(config)  free(config);
  127.     if(objects) free(objects);
  128.     if(libs)    free(libs);
  129.     if(command) free(command);
  130.     if(ppopts)  free(ppopts);
  131.     if(options) free(options);
  132.     if(linkcmd) free(linkcmd);
  133. #ifdef AMIGA
  134.     if(ap) free(ap);
  135. #endif
  136.     free_namelist(first_obj);
  137.     free_namelist(first_scratch);
  138.     exit(rc);
  139. }
  140. void add_name(char *obj,struct NameList **first,struct NameList **last)
  141. {
  142.     struct NameList *new;
  143.     if(flags&VERYVERBOSE) printf("add_name: %s\n",obj);
  144.     if(!(new=(struct NameList *)malloc(sizeof(struct NameList))))
  145.         {printf(nomem);raus(20);}
  146.     if(!(new->obj=(char *)malloc(strlen(obj)+1)))
  147.         {free((void *)new);printf(nomem);raus(20);}
  148.     if(first==&first_obj) linklen+=strlen(obj)+1;
  149.     strcpy(new->obj,obj);
  150.     new->next=0;
  151.     if(!*first){
  152.         *first=*last=new;
  153.     }else{
  154.         (*last)->next=new;*last=new;
  155.     }
  156. }
  157. int read_config(const char *cfg_name)
  158. {
  159.     int i,count; long size;
  160.     char *p,*name;
  161.     FILE *file=0;
  162.     for(i=0;i<sizeof(search_dirs)/sizeof(search_dirs[0]);i++){
  163.       name=malloc(strlen(search_dirs[i])+strlen(cfg_name)+1);
  164.       if(!name) {printf(nomem);raus(EXIT_FAILURE);}
  165.       strcpy(name,search_dirs[i]);
  166.       strcat(name,cfg_name);
  167.       file=fopen(name,"rb");
  168.       free(name);
  169.       if(file) break;
  170.     }
  171.     if(!file) {puts("No config file!");raus(EXIT_FAILURE);}
  172.     if(fseek(file,0,SEEK_END)) return 0;
  173.     size=ftell(file);
  174.     if(fseek(file,0,SEEK_SET)) return 0;
  175.     config=malloc(size);
  176.     if(!config){printf(nomem);raus(EXIT_FAILURE);}
  177.     fread(config,1,size,file);
  178.     fclose(file);
  179.     count=0;p=config;
  180.     while(p<config+size&&*p){
  181.         count++;
  182.         while(p<config+size&&*p!='\n') p++;
  183.         if(*p=='\n') *p++=0;
  184.     }
  185.     confp=malloc(count*sizeof(char *));
  186.     for(p=config,i=0;i<count;i++){
  187.         confp[i]=p;
  188.         while(*p) p++;
  189.         p++;
  190.     }
  191.     return count;
  192. }
  193.  
  194. int main(int argc,char *argv[])
  195. {
  196.     int tfl,i,len=10,pm,count;char *parm;long opt=1;
  197.     for(i=1;i<argc;i++){
  198.         if(argv[i][0]=='+'){
  199.             config_name=argv[i]+1;
  200.             argv[i][0]=0;
  201.             break;
  202.         }
  203.     }
  204.     count=read_config(config_name);
  205. #ifdef AMIGA
  206.     if(pm=DOSBase->lib_Version>=36){
  207.         if(ap=(struct AnchorPath *)calloc(sizeof(struct AnchorPath)+NAMEBUF,1))
  208.             {ap->ap_Strlen=NAMEBUF;ap->ap_BreakBits=0;} else pm=0;
  209.     }
  210. #endif
  211.     for(i=1;i<argc+count;i++){
  212.         if(i<argc) parm=argv[i]; else parm=confp[i-argc];
  213.         if(!strncmp(parm,"-ul=",4)){ul=parm+4;*parm=0;}
  214.     }
  215.     for(i=1;i<argc+count;i++){
  216.         if(i<argc) parm=argv[i]; else parm=confp[i-argc];
  217. /*        printf("Parameter %d=%s\n",i,parm);*/
  218.         if(!strncmp(parm,"-ml=",4)){MAXCLEN=atoi(parm+4);*parm=0;}
  219.         if(!strncmp(parm,"-pp=",4)){ppname=parm+4;*parm=0;}
  220.         if(!strncmp(parm,"-cc=",4)){ccname=parm+4;*parm=0;}
  221.         if(!strncmp(parm,"-as=",4)){asname=parm+4;*parm=0;}
  222.         if(!strncmp(parm,"-ld=",4)){ldname=parm+4;*parm=0;}
  223.         if(!strncmp(parm,"-l2=",4)){l2name=parm+4;*parm=0;}
  224.         if(!strncmp(parm,"-rm=",4)){rmname=parm+4;*parm=0;}
  225.         if(!strncmp(parm,"-ppv=",5)){ppv=parm+5;*parm=0;}
  226.         if(!strncmp(parm,"-ccv=",5)){ccv=parm+5;*parm=0;}
  227.         if(!strncmp(parm,"-asv=",5)){asv=parm+5;*parm=0;}
  228.         if(!strncmp(parm,"-ldv=",5)){ldv=parm+5;*parm=0;}
  229.         if(!strncmp(parm,"-l2v=",5)){l2v=parm+5;*parm=0;}
  230.         if(!strncmp(parm,"-rmv=",5)){rmv=parm+5;*parm=0;}
  231.         if(!strncmp(parm,"-cf=",4)){cf=parm+4;*parm=0;}
  232.         if(!strncmp(parm,"-isc=",5)){scname=parm+5;*parm=0;}
  233.         if(!strncmp(parm,"-iscv=",6)){scv=parm+6;*parm=0;}
  234.         if(!strcmp(parm,"-schedule")) {flags|=SCHEDULER;*parm=0;}
  235.         if(!strcmp(parm,"-notmpfile")) {flags|=NOTMPFILE;*parm=0;}
  236.         if(!strcmp(parm,"-E")) {flags|=CCSRC;*parm=0;}
  237.         if(!strcmp(parm,"-S")) {flags|=ASSRC;*parm=0;}
  238.     if(!strcmp(parm,"-SCS")) {flags|=SCSRC;*parm=0;}
  239.         if(!strcmp(parm,"-c")) {flags|=OBJ;*parm=0;}
  240.         if(!strcmp(parm,"-v")) {flags|=VERBOSE;*parm=0;}
  241.         if(!strcmp(parm,"-h")) {flags|=VERBOSE;*parm=0;}
  242.         if(!strcmp(parm,"-k")) {flags|=KEEPSCRATCH;*parm=0;}
  243.         if(!strcmp(parm,"-vv")) {flags|=VERBOSE|VERYVERBOSE;*parm=0;}
  244.         if(!strcmp(parm,"-nostdlib")) {flags|=NOSTDLIB;*parm=0;}
  245.         if(!strncmp(parm,"-O",2)){
  246.             if(parm[2]=='0') opt=0;
  247.             else if(parm[2]=='1'||parm[2]==0) opt=991;
  248.             else if(parm[2]=='2') {opt=1023;flags|=SCHEDULER;}
  249.             else if(parm[2]>='3'&&parm[2]<='9') {opt=~0;flags|=SCHEDULER;}
  250.             else if(parm[2]=='=') opt=atoi(&parm[3]);
  251.             *parm=0;
  252.         }
  253.         if(!strcmp(parm,"-o")&&i<argc-1) {
  254.             *argv[i++]=0;destname=argv[i];
  255.             flags|=OUTPUTSET;argv[i]="";continue;
  256.         }
  257.         if(!strncmp(parm,"-o=",3)){
  258.             destname=parm+3;
  259.             flags|=OUTPUTSET;*parm=0;continue;
  260.         }
  261.         if(parm[0]=='-'&&parm[1]=='l'){
  262.             size_t l=strlen(userlibs);
  263.             if((l+strlen(parm)-2+strlen(ul)+1)>=USERLIBS){puts("Userlibs too long");exit(20);}
  264.             userlibs[l]=' ';
  265.             sprintf(userlibs+l+1,ul,parm+2);
  266.             *parm=0;continue;
  267.         }
  268.         len+=strlen(parm)+10;
  269.     }
  270.     if(flags&VERBOSE) printf("vc frontend for vbcc (c) in 1995-98 by Volker Barthelmann\n");
  271.     if(!(flags&7)) flags|=OBJ+1;
  272.     tfl=flags&7;
  273.     if(scname==empty) flags&=~SCHEDULER;
  274.     if(flags&VERYVERBOSE){
  275.       ppname=ppv;ccname=ccv;asname=asv;ldname=ldv;
  276.       rmname=rmv;l2name=l2v;scname=scv;
  277.     }
  278.     if(flags&NOSTDLIB){ldname=l2name;}
  279.     /*  Nummer sicher...    */
  280.     len+=strlen(ppname)+strlen(ccname)+strlen(asname)+
  281.          strlen(rmname)+strlen(scname)+strlen(userlibs)+NAMEBUF;
  282.     if(!(command=malloc(len))){printf(nomem);raus(20);}
  283.     if(!(options=malloc(len))){printf(nomem);raus(20);}
  284.     if(!(ppopts=malloc(len))){printf(nomem);raus(20);}
  285.     *options=0;*ppopts=0;
  286.     for(i=1;i<argc+count;i++){
  287.         if(i<argc) parm=argv[i]; else parm=confp[i-argc];
  288.         if(*parm=='-'){
  289.             if(parm[1]!='D'&&parm[1]!='I'&&parm[1]!='+'){
  290.                 strcat(options,parm);strcat(options," ");
  291.             }else{
  292.                 strcat(ppopts,parm);strcat(ppopts," ");
  293.             }
  294.         }
  295.     }
  296.     if(flags&VERYVERBOSE) printf("flags=%d opt=%ld len=%d\n",flags,opt,len);
  297.     namebuf[0]='\"'; namebuf2[0]='\"';
  298.     for(i=1;i<argc;i++){
  299.         int t,j;char *file;
  300. #ifdef AMIGA
  301.         BPTR lock;
  302. #endif
  303.         if(i<argc) parm=argv[i]; else parm=confp[i-argc];
  304.         if(*parm=='-'||!*parm) continue;
  305.         if(flags&VERYVERBOSE) printf("Argument %d:%s\n",i,parm);
  306. #ifdef AMIGA
  307.         if(pm) if(MatchFirst((STRPTR)parm,ap)) {printf("No match for %s\n",parm);continue;}
  308. #endif
  309.         do{
  310. #ifdef AMIGA
  311.             if(pm) file=(char *)&ap->ap_Buf[0]; else file=parm;
  312.             t=typ(file);
  313.             if(pm&&(lock=Lock((STRPTR)file,-2))){
  314.                 NameFromLock(lock,(STRPTR)namebuf+1,NAMEBUF-2);
  315.                 strcat(namebuf,"\"");
  316.                 file=namebuf;
  317.                 UnLock(lock);
  318.             }else{
  319.                 strcpy(namebuf+1,file);
  320.                 strcat(namebuf,"\"");
  321.                 file=namebuf;
  322.             }
  323. #else
  324.             file=parm;
  325.             t=typ(file);
  326.             strcpy(namebuf+1,file);
  327.             strcat(namebuf,"\"");
  328.             file=namebuf;
  329. #endif
  330.             if(flags&VERYVERBOSE) printf("File %s=%d\n",file,t);
  331.             for(j=t;j<tfl;j++){
  332.                 if(j==OBJ){ if(j==t) add_name(file,&first_obj,&last_obj);
  333.                             continue;}
  334.                 strcpy(oldfile,file);
  335.                 if(j==t&&j!=tfl-1&&!(flags&(NOTMPFILE|KEEPSCRATCH))){
  336.                     file=namebuf2;
  337.                     tmpnam(file+1);
  338.                 }
  339.                 if(j==tfl-1) file=namebuf;
  340.                 if(j==PPSRC){
  341.                     file=add_suffix(file,".i");
  342.                     if(tfl==CCSRC&&(flags&OUTPUTSET)) file=destname;
  343.                     sprintf(command,ppname,ppopts,oldfile,file);
  344.                     if((tfl)!=CCSRC) add_name(file,&first_scratch,&last_scratch);
  345.                 }
  346.         /* MUST come before CCSRC-handling! */
  347.                 if(j==SCSRC){
  348.                     file=add_suffix(file,".asm");
  349.                     if(tfl==ASSRC&&(flags&OUTPUTSET)) file=destname;
  350.                     sprintf(command,scname,oldfile,file);
  351.                     if(tfl!=ASSRC) add_name(file,&first_scratch,&last_scratch);
  352.                 }
  353.                 if(j==CCSRC){
  354.             if(flags&SCHEDULER){
  355.               file=add_suffix(file,".scs");
  356.             }else{
  357.               if(++j==tfl-1) file=namebuf;
  358.               file=add_suffix(file,".asm");
  359.             }
  360.                     if(tfl==j+1&&(flags&OUTPUTSET)) file=destname;
  361.                     sprintf(command,ccname,oldfile,file,options,opt);
  362.                     if(tfl!=j+1) add_name(file,&first_scratch,&last_scratch);
  363.                 }
  364.                 if(j==ASSRC){
  365.                     file=add_suffix(file,".o");
  366.                     if(tfl==OBJ&&(flags&OUTPUTSET)) file=destname;
  367.                     sprintf(command,asname,oldfile,file);
  368.                     add_name(file,&first_obj,&last_obj);
  369.                     if((tfl)!=OBJ) add_name(file,&first_scratch,&last_scratch);
  370.                 }
  371.                 if(flags&VERBOSE) printf("%s\n",command);
  372.                 if(system(command)){printf("%s failed\n",command);raus(20);}
  373.             }
  374. #ifdef AMIGA
  375.         }while(pm&&!MatchNext(ap));
  376.         if(pm) MatchEnd(ap);
  377. #else
  378.         }while(0);
  379. #endif
  380.     }
  381.     if((tfl)>OBJ){
  382.     /*  Zu Executable linken    */
  383.         struct NameList *p;
  384.         FILE *objfile=0;
  385.         char *tfname;
  386.         objects=malloc(linklen);
  387.         if(!objects){printf(nomem);raus(EXIT_FAILURE);}
  388.         linklen+=strlen(ldname)+strlen(destname)+strlen(userlibs)+10;
  389.         if(flags&VERYVERBOSE) printf("linklen=%d\n",linklen);
  390.         if(!(linkcmd=(char *)malloc(linklen))){printf(nomem);raus(20);}
  391.         p=first_obj;
  392.         if(linklen>=MAXCLEN){
  393.         tfname=tmpnam(0);
  394.         sprintf(objects,cf,tfname);
  395.             if(!(objfile=fopen(tfname,"w"))){
  396.                 printf("Could not open <%s>!\n",tfname);
  397.                 raus(20);
  398.             }
  399.         }else *objects=0;
  400.         while(p){
  401.             if(p->obj){
  402.                 if(linklen>=MAXCLEN){
  403.                     fputs(p->obj,objfile);
  404.                     fputs("\n",objfile);
  405.                 }else{
  406.                     strcat(objects,p->obj);strcat(objects," ");
  407.                 }
  408.             }
  409.             p=p->next;
  410.         }
  411.         if(objfile) fclose(objfile);
  412.         if(*objects){
  413.             sprintf(linkcmd,ldname,objects,userlibs,destname);
  414.             if(flags&VERBOSE) printf("%s\n",linkcmd);
  415.             /*  hier wird objfile bei Fehler nicht geloescht    */
  416.             if(system(linkcmd)){printf("%s failed\n",linkcmd);raus(20);}
  417. #ifdef AMIGA
  418.             if(flags&VERBOSE){
  419.                 BPTR l;
  420.                 if(l=Lock((STRPTR)destname,-2)){
  421.                     if(Examine(l,&fib)) printf("Size of executable: %lu bytes\n",(unsigned long)fib.fib_Size);
  422.                     UnLock(l);
  423.                 }
  424.             }
  425. #endif
  426.         }else puts("No objects to link");
  427.         if(objfile) remove(tfname);
  428.     }
  429.     if(!(flags&KEEPSCRATCH)) del_scratch(first_scratch);
  430.     raus(0);
  431. }
  432.  
  433. int typ(char *p)
  434. {
  435.     p=strrchr(p,'.');
  436.     if(!p) return 5;
  437.     if(!strcmp(p,".c")) return PPSRC;
  438.     if(!strcmp(p,".i")) return CCSRC;
  439.     if(!strcmp(p,".s")) return ASSRC;
  440.     if(!strcmp(p,".asm")) return ASSRC;
  441.     if(!strcmp(p,".scs")) return SCSRC;
  442.     if(!strcmp(p,".o")) return OBJ;
  443.     if(!strcmp(p,".obj")) return OBJ;
  444.     return OBJ;
  445. }
  446.  
  447. char *add_suffix(char *s,char *suffix)
  448. {
  449.     static char str[NAMEBUF+3],*p;
  450.     if(strlen(s)+strlen(suffix)>NAMEBUF){printf("string too long\n");raus(20);}
  451.     if(s!=str) strcpy(str,s);
  452.     p=strrchr(str,'.');
  453.     if(!p) p=str+strlen(s);
  454.     strcpy(p,suffix);
  455.     strcat(p,"\"");
  456.     return str;
  457. }
  458.